查看原文
其他

热修复的几种方案,你可知否?

别叫阿迪 终端研发部 2022-08-26
点击上方的终端研发部,右上角选择“设为星标
每日早10点半,技术文章准时送上
公众号后台回复“学习”,获取作者独家秘制精品资料


往期文章

记五月的一个Android面试经

今日头条屏幕适配方案落地研究

Flutter  + MVP +Kotlin 实战!

知乎:APP的 Gradle plugin 实践

从400多k的大小减到了2B,我的APP是怎么优化的?

来源:别叫阿迪

原文链接:https://www.jianshu.com/p/76d15810a8f5

插件化和热修复是Android开发较为高级的知识点,是中级开发人员通向高级开发中必备知识点,插件化知识:插件化。下文是对热修复的总结:

什么是热修复?

1.软件发布之后,总会出现一些Bug,这个时候就需要去解决bug然后测试,并打渠道包在各大应用市场上发布,这样就会耗费大量的人力物力。

2.升级版本的成功率不太高,而且需要很长的时间来覆盖之前的版本,这样旧版本的bug就会一直影响着没有升级版本的用户。

3.如果碰到某些节日活动,需要更改小功能,并且要短时间内完成版本覆盖,升级版本根本完成不了。这样就用到了热修复热更新,热修复不需要重新发布版本,用户也不需要下载最新的版本,而且修复的成功率也高,他会偷偷的修改bug并且更新版本。

简单来讲,热修复就是为了修复线上问题而提出的修补方案,程序修补过程无需重新发版。

优点:

正常开发软件流程一般是:线下开发→上线→发现bug→紧急修复上线。这种方式代价太大。

而热修复的开发流程显得更加灵活,能及时修复bug,补丁包采用差量技术,生成的PATCH体积小,对应用没有侵入,几乎没有性能损耗。无需重新发布版本,实时高效热修复,无需下载新的应用。

但也有缺点:只能基于方法修复,而且兼容性不太好,不支持新增字段和修改方法,也不支持替换资源。

当前热门的热修复技术

1:qq空间超级补丁

2:微信Tinker

3:饿了么Amigo

4:美团Robust :

5:360RePlugin :

6:滴滴出行VirtualAPK 等

热修复实现原理

热修复是基于dex分包方案,和Android虚拟机的类加载器(ClassLoader)实现的

dex分包原理:在打包apk的时候,会把java文件通过类加载器编译成class文件,然后把class文件组合成class.dex文件,目的是把不同class文件重复的东西只需保留一份,dex文件会把每一个类的id检索起来,存在一个链表里面,这个链表的长度是用short类型存储的,最大值是65536,也就是单个dex文件的方法数上限为65536。方法数包括引用的framwork方法,library方法,还有自己写的代码方法。因为在生成.dex文件之后会生成一些多余的资源,所以系统会对dex文件进行优化,会分配一个缓冲区,缓冲区大小的限制:在android2.x的系统上缓冲区只有5MB,android4.x为8MB或者16MB,如果方法数量超过缓冲区的大小时,会造成dexopt崩溃,所以我们一般apk的方法数要控制在65536以内,如果超出,就要考虑dex分包,api14(Android5.0)之前是不支持分包的

分包解决方案:将编译好的class文件,拆分成多个dex文件,将应用启动时必须用到的类和这些类的应用类放到主dex文件,其他代码放到次dex文件,当应用启动的时候先加载主dex文件,等到应用启动后再动态的加载次dex文件。

类加载器:java的类加载器是加载class文件,而Android的虚拟机无论是dvm还是art都只能识别dex文件,所以java的类加载器在Android中不适用,Android中的 Java.lang.ClassLoader类也不同与java中的Java.lang.ClassLoader类。

Android虚拟机类加载机制:Android虚拟机是从dex文件里面去加载一个类,虚拟机定义的关于类的加载规范必须被实现,他规定每个ClassLoader都得有一个父亲ClassLoader,以此形成一个父子的多层级关系,利用这个层级关系实现了类的双亲委派机制, 在Android虚拟机里的ClassLoader层级关系为ClassLoader—>BaseDexClassLoader —>Dex ClassLoader和PathClassLoader,其中PathClassLoader是用来加载Android系统类和应用的类DexClassLoader支持加载APK、DEX和JAR,也可以从SD卡进行加载 ClassLoader类根据一个指定的类名称,找到或者生成相应的字节码,然后从这些字节码中定义出一个java类 DexClassLoader和PathClassLoader都属于符合双亲委派模型的类加载器(因为它们没有重载loadClass方法)。也就是说,它们在加载一个类之前,回去检查自己以及自己以上的类加载器是否已经加载了这个类。如果已经加载过了,就会直接将之返回,而不会重复加载

类加载热修复:当分包完成之后,会形成一个dex包的有序数组,当需要加载类加载器的时候,会从数组中第一个dex包开始加载,直到找到这个类为止,当多个dex包中都有这个文件的时候,就取第一个文件,热修复是通过将已经修复了的bug包打成dex包,并将这个dex包放在有序数组的第一个,当加载类文件的时候,首先会找到修改好的dex包去替换之前存在bug的dex包,而排在后面的存在bug的dex包根据类加载器的双亲委派机制不会被加载,这就是类加载热修复方法的实现。

热修复三方框架:Nuwa,这个框架实现ClassLoader加载dex文件

要弄清热修复技术的原理,就要先弄清Android的ClassLoader机制。Android的ClassLoader分为PathClassLoader和DexClassLoader,它们都都继承自BaseDexClassLoader,其中PathClassLoader用来加载系统类和应用类;DexClassLoader用来加载jar、apk、dex文件。例如下面要介绍的阿里的Andfix和Sophix的原理如下:

AndFix:

由补丁类的classLoader加载补丁类,在native层针对不同Android架构中的不同的ArtMethod结构调用对应的replaceMethod方法按照定义好的ArtMethod结构一一替换方法的所有信息如所属类、访问权限、代码内存地址等。稳定性较差,会受到国内ROM厂商对ArtMethod结构更改的影响,所以这正是AndFix不支持很多机型的原因。

Sophix:

由补丁类的classLoader加载补丁类,在native层直接memcpy(smeth,dmth,sizeof(ArtMethod))替换整个artMethod的结构。初始化类时会为这个类分配空间,AllocArtMethodArray会紧挨着的new出来放入art中的方法数组中。通过计算辅助类的前后两个方法的起始地址就可以计算出artMethod结构的大小了。注:补丁类初始化时,也会分配自己的artMethod空间,拿这个修复过的新ArtMethod去替换旧ArtMethod的内容,不用管ArtMethod的结构。稳定性大大提高!

代码修复有两大主要方案:一种是阿里系的底层替换方案,另一种是腾讯系的类加载方案。底层替换方案限制颇多,但时效性最好,加载轻快,立即见效。类加载方案时效性差,需要重新冷启动才能见效,但修复范围广,限制少。

阅读更多

2019最新Android面试题知乎:APP的 Gradle plugin 实践
Gradle更小、更快构建APP的奇淫技巧关于Gradle, 搞定Groovy闭包这一篇就够了为什么我把 Run 出来的 Apk 发给老板,却装不上!
Google:就算Linux自带多进程通信,我也要采用Binder机制!

相信自己,没有做不到的,只有想不到的

在这里获得的不仅仅是技术!

喜欢就给个“在看” 

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存